package com.xywei.config.security;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import com.xywei.domain.Authority;
import com.xywei.domain.Resource;

public class SecurityCustomMetadataSource implements FilterInvocationSecurityMetadataSource {

	@Autowired
	private SecurityService securityService;

	/**
	 * 每个资源URL需要哪些权限
	 */
	private static Map<String, Collection<ConfigAttribute>> resourceAuthority = null;

	/**
	 * 
	 * @Description 启动系统就初始化权限数据
	 * @Datetime 2021年3月21日 下午2:04:34<br/>
	 */
	public void initResourceConfigAuthority() {

		if (resourceAuthority == null) {
			// 格式: ["url"="['权限1'，'权限2']"]
			resourceAuthority = new HashMap<String, Collection<ConfigAttribute>>();
			// 获取数据库的权限表所有数据，带URL资源
			Set<Authority> authoritiesWithResource = securityService.getAuthoritiesWithResource();

			if (authoritiesWithResource != null) {
				// 一个资源, 对应多个权限
				resourceAuthority = obtainUrlWithAuthority(authoritiesWithResource);
			}

		}
	}

	private Map<String, Collection<ConfigAttribute>> obtainUrlWithAuthority(Set<Authority> authoritiesWithResource) {

		Map<String, Collection<ConfigAttribute>> resourceAuthority = new HashMap<String, Collection<ConfigAttribute>>();
		// 权限的名字在设计的时候就决定了是唯一的
		for (Authority authority : authoritiesWithResource) {
			String authorityName = authority.getAuthorityName();
			Set<Resource> resources = authority.getResources();
			for (Resource resource : resources) {
				// 跳过父菜单目录
				if (resource.getParentId() == null) {
					continue;
				}
				String url = resource.getUrl();
				ConfigAttribute attribute = new SecurityConfig(authorityName);
				Collection<ConfigAttribute> attributes = new HashSet<ConfigAttribute>();
				if (resourceAuthority.containsKey(url)) {
					attributes = resourceAuthority.get(url);
				}
				attributes.add(attribute);
				resourceAuthority.put(url, attributes);
			}
		}

		return resourceAuthority;
	}

	/**
	 * 获取访问某个资源所需要的权限
	 */
	@Override
	public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {

		HttpServletRequest request = ((FilterInvocation) object).getRequest();
		if (resourceAuthority != null) {
			Set<String> urls = resourceAuthority.keySet();
			if (urls != null) {
				for (String url : urls) {
					AntPathRequestMatcher antPathRequestMatcher = new AntPathRequestMatcher(url);
					if (antPathRequestMatcher.matches(request)) {
						return resourceAuthority.get(url);
					}
				}
			}
		}
		// 表示不需要权限，当前看security配置，只要认证了就可以访问！
		return null;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}

}
